﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BusinessTier.Facade.Interface;
using BusinessTier.DataContext;
using Domain;
using Domain.Type;

namespace BusinessTier.Facade.Implementation
{
    public class ProductService : IProductService
    {
        public decimal CalculatePrice(string productType, int quantity, ColorMode colorMode, string printMediaCode, int formFactorId)
        {
            using (var ctx = new SimplyData())
            {
                ProductPrice lowerPrice = ctx.ProductPrices.OrderByDescending(p => p.Quantity).First(p => p.FormFactor.Product.ProductTypeId.Equals(productType) && p.Quantity <= quantity && p.FormFactor.FormFactorId == formFactorId);
                ProductPrice upperPrice = ctx.ProductPrices.OrderBy(p => p.Quantity).FirstOrDefault(p => p.FormFactor.Product.ProductTypeId.Equals(productType) && p.Quantity >= quantity && p.FormFactor.FormFactorId == formFactorId);

                if (upperPrice == null)
                {
                    upperPrice = lowerPrice;
                }
                decimal lowPrVal = 0;
                decimal upperPrVal = 0;

                switch (colorMode)
                {
                    case ColorMode.Mode4x0:
                        lowPrVal = lowerPrice.Price4x0;
                        upperPrVal = upperPrice.Price4x0;
                        break;
                    case ColorMode.Mode4x4:
                        lowPrVal = lowerPrice.Price4x4;
                        upperPrVal = upperPrice.Price4x4;
                        break;
                    case ColorMode.Mode1x0:
                        lowPrVal = lowerPrice.Price1x0;
                        upperPrVal = upperPrice.Price1x0;
                        break;
                    case ColorMode.Mode1x1:
                        lowPrVal = lowerPrice.Price1x1;
                        upperPrVal = upperPrice.Price1x1;
                        break;
                    case ColorMode.Mode4x1:
                        lowPrVal = lowerPrice.Price4x1;
                        upperPrVal = upperPrice.Price4x1;
                        break;
                }

                decimal price = lowPrVal;
                if (upperPrice.Quantity != lowerPrice.Quantity)
                {
                    price = lowPrVal - ((lowPrVal - upperPrVal) / (upperPrice.Quantity - lowerPrice.Quantity)) * (quantity - lowerPrice.Quantity);
                }


                price = price * quantity;

                if (!lowerPrice.DefaultPrintMedia.PrintMediaCode.Equals(printMediaCode))
                {
                    decimal defaultPaperPrice = lowerPrice.DefaultPrintMedia.Price;//ctx.PrintMedias.Find(lowerPrice.DefaultPrintMedia.PrintMediaCode).Price;
                    decimal currentMediaPrice = ctx.PrintMedias.Find(printMediaCode).Price;

                    price = price + (currentMediaPrice - defaultPaperPrice) * Convert.ToDecimal(quantity/lowerPrice.FormFactor.CountInA4);
                }

                return price;
            }
            
        }



        public IEnumerable<ProductType> GetAllProductTypes()
        {
            using(var ctx = new SimplyData())
            {
                return ctx.ProductTypes.OrderBy(p => p.ProductTypeId).ToList();
            }
        }

        public IEnumerable<ProductType> GetAllProductTypesWithMediaAndFFactors()
        {
            using (var ctx = new SimplyData())
            {
                return ctx.ProductTypes.Include("PrintMedias").Include("FormFactors").OrderBy(p => p.ProductTypeId).ToList();
            }
        }

        public IEnumerable<ProductPrice> GetReferenceProductPrice()
        {
            using (var ctx = new SimplyData())
            {
                return ctx.ProductPrices.Include("FormFactor")
                                        .Where(p => p.DefaultDisplay == true && p.FormFactor.Product.IsEndProduct == true && p.FormFactor.IsDefault)
                                        .OrderBy(p => p.FormFactor.Product.SortKey).ToList();
            }
        }


        public ProductType GetProductByFormfactorId(int formFactorId)
        {
            using (var ctx = new SimplyData())
            {
                return ctx.FormFactors.First(p => p.FormFactorId == formFactorId).Product;
                                        
            }
        }

        public IEnumerable<PrintMedia> GetAllPrintMedias()
        {
            using (var ctx = new SimplyData())
            {
                return ctx.PrintMedias.OrderBy(p => p.PrintMediaCode).ToList();
            }
        }


        public IEnumerable<ProductPrice> GetProductPriceListByType(string type)
        {
            using (var ctx = new SimplyData())
            {
                return ctx.ProductPrices.Include("FormFactor")
                    .Where(p => p.FormFactor.Product.ProductTypeId == type)
                    .OrderBy(p => p.FormFactor.FormFactorId)
                    .OrderBy(p => p.Quantity).ToList();
            }
        }





        public PrintMedia GetDefaultPrintMedia(int formFactorId)
        {
            using (var ctx = new SimplyData())
            {
                var price = ctx.ProductPrices
                    .FirstOrDefault(p => p.FormFactor.FormFactorId == formFactorId);
                if (price != null)
                {
                    return price.DefaultPrintMedia;
                }
                return null;
            }
        }
    }
}
